package com.sky.myapplication.kotlin.kotlinActivity

import android.app.Activity
import android.os.Bundle
import android.util.Log
import com.sky.myapplication.kotlin.`class`.DataPersonKotlin
import com.sky.myapplication.kotlin.`class`.InterfacePersonKotlin
import com.sky.myapplication.kotlin.`class`.PersonKotlin
import com.sky.myapplication.kotlin.`class`.StudentKotlin
import java.lang.IllegalArgumentException

/**
 * Created by Min
 * Time 2023/2/8
 * Desc
 */
class PractiveCodeKotlinActivity : Activity() {
    //Kotlin的空安全设计对于声明可为空的参数，在使用时要进行空判断处理，有两种处理方式，
    // 字段后加!!像Java一样抛出空异常，另一种字段后加?可不做处理返回值为 null 或配合 ?: 做空判断处理

    //var  可变变量定义：var 关键字
    //val  不可变变量定义：val 关键字，只能赋值一次的变量(类似Java中final修饰的变量)

    //类型后面加?表示可为空
    var age : String? = "23"
    //抛出空指针异常
    val ages = age!!.toInt()
    //不做处理返回 null
    val ages1 = age?.toInt()
    //age为空返回-1
    val age2 = age?.toInt() ?: -1

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        printWords("a", "b", "c")
        Log.i("mxp", parseInt("aa").toString())

        parseInt("2", "3")

        getLoop()

        var value = 1
        val value1: Int? = value
        val value2: Int? = value
        compareValue(value1, value2)

        shlValue(2, 1)

        Log.i("mxp", "decimalDigitValue:..." + decimalDigitValue('4'))

        printArray()

        var person = PersonKotlin("lion")
        person.sayName()

        var fruit = PersonKotlin.Fruit()
        Log.i("mxp", "fruit..." + fruit.color())

        val student = StudentKotlin("Linda")
        student.sayName()

        var data = DataPersonKotlin("lion", 12)
        var newData = data.copy(name = "Tom")
        Log.i("mxp", "data..." + data.name)
        Log.i("mxp", "newData..." + newData.name)
    }

    //函数的变长参数可以用 vararg 关键字进行标识：
    fun printWords(vararg words : String){
        for (word in words){
//            print(word)
            Log.i("mxp", word)
        }
    }

    //当一个引用可能为 null 值时, 对应的类型声明必须明确地标记为可为 null。 当 str 中的字符串内容不是一个整数时, 返回 null:
    fun parseInt(str: String): Int?{
        //toIntOrNull返回为空，使用toInt()会闪退，toIntOrNull()异常会返回null
        return str.toIntOrNull()
    }

    fun parseInt(str1: String, str2: String){
        val x = parseInt(str1)
        val y = parseInt(str2)

        //第一种写法
        if (x != null && y != null){
            Log.i("mxp", (x * y).toString())
        } else {
            Log.i("mxp", "params is not a number")
        }

        //第二中写法
        if (x == null){
            Log.i("mxp", "params one is wrong number")
            return
        }
        if (y == null){
            Log.i("mxp", "params two is wrong number")
            return
        }
        Log.i("mxp", (x * y).toString())
    }

    //类型检测及自动类型转换
    //我们可以使用 is 运算符检测一个表达式是否某类型的一个实例(类似于Java中的instanceof关键字)。
    //Any类型是Kotlin所有非空类型的超类型（非空类的根）,包含像Int这样的基本数据类型。如果你需要可以持有任何可能值得变量，包含null在内，则必须使用Any？类型。在底层，Any类型对应java.lang.Object，在Kotlin函数使用Any 时，它会编译成为Java字节码的Object。
    fun getStringLength(obj : Any): Int?{
        if (obj is String){
            return obj.length
        }
        return null

        //在这里还有一种方法，与Java中instanceof不同，使用!is
        if(obj !is String)
            return null
        return obj.length

        if (obj is String && obj.length > 0)
            return obj.length
        return null
    }


    //区间表达式由具有操作符形式 .. 的 rangeTo 函数辅以 in 和 !in 形成。 区间是为任何可比较类型定义的，但对于整型原生类型，它有一个优化的实现。
    fun getLoop(){
        for (number in 1..4)// 输出“1234”  等同于 1 <= i && i <= 4
            Log.i("mxp", number.toString())

        for (number in 4..1)// 什么都不输出
            Log.i("mxp", number.toString())

        // 使用 step 指定步长,间隔数量
        for (number in 1..10 step 2)
            Log.i("mxp step", number.toString())

        for (number in 10 downTo 1 step 2)//downTo降序输出
            Log.i("mxp downTo", number.toString())

        for (number in 1 until 10)// 使用 until 函数排除结束元素
            Log.i("mxp until", number.toString())// i in [1, 10) 排除了 10
    }



//    下面是所有类型的字面常量：
//    十进制：123
//    长整型以大写的 L 结尾：123L
//    16 进制以 0x 开头：0x0F
//    2 进制以 0b 开头：0b00001011
//    注意：8进制不支持
//    Kotlin 同时也支持传统符号表示的浮点数值：

//    Doubles 默认写法: 123.5, 123.5e10
//    Floats 使用 f 或者 F 后缀：123.5f

    //在 Kotlin 中，三个等号 === 表示比较对象地址，两个 == 表示比较两个值大小。
    fun compareValue(value1 : Int?, value2 : Int?){
        Log.i("mxp", (value1 === value1).toString())// true，值相等，对象地址相等

        Log.i("mxp", (value1 === value2).toString())//  false，值相等，对象地址不一样
        Log.i("mxp", (value1 == value2).toString())// true，值相等
    }

//    每种数据类型都有下面的这些方法，可以转化为其它的类型：
//    toByte(): Byte
//    toShort(): Short
//    toInt(): Int
//    toLong(): Long
//    toFloat(): Float
//    toDouble(): Double
//    toChar(): Char

//    位操作符 - 对于Int和Long类型，还有一系列的位操作符可以使用，分别是：
//    shl(bits) – 左移位 (Java’s <<)
//    shr(bits) – 右移位 (Java’s >>)
//    ushr(bits) – 无符号右移位 (Java’s >>>)
//    and(bits) – 与
//    or(bits) – 或
//    xor(bits) – 异或
//    inv() – 反向
    fun shlValue(number: Int, position: Int){
        Log.i("mxp", "shlValue:..." + number.shl(position))
    }

    //字符字面值用单引号括起来: '1'。 特殊字符可以用反斜杠转义。 支持这几个转义序列：\t、 \b、\n、\r、\'、\"、\\ 和 \$。 编码其他字符要用 Unicode 转义序列语法：'\uFF00'。
    fun decimalDigitValue(c: Char): Int{
        if (c !in '0'..'9')
            throw IllegalArgumentException("Out of range")
        return c.toInt()
    }

    fun printArray(){
        //[1,2,3]
        val a = arrayOf(1, 2, 3)
        //[0,2,4]
        val b = Array(5, { i -> {i + 1}})
        val c = Array(5, { it + 1})

        //读取数组内容

        Log.i("mxp", "printArray..." + a)
        printArrayValue(a)

        Log.i("mxp", "printArray..." + b)
//        printArrayValue(b)

        Log.i("mxp", "printArray..." + c)
        printArrayValue(c)
    }

    fun printArrayValue(values : Array<Int>){
        for (v in values)
            Log.i("mxp", "printArray..." + v)
    }

//    字符串模板
//    字符串可以包含模板表达式 ，即一些小段代码，会求值并把结果合并到字符串中。 模板表达式以美元符
//    val i = 10
//    val s = "i = $i" // 求值结果为 "i = 10"

//    val price = """
//    ${'$'}9.99
//    """
//    println(price)  // 求值结果为 $9.99

    fun whenValue(){
        var x = 2
        when(x){
            1 -> Log.i("mxp", "whenValue...1")
            2, 3 -> Log.i("mxp", "whenValue...2, 3")
            //值在（in）或者不在（!in）一个区间或者集合中：
            in 1..10 -> Log.i("mxp", "x is in the range")
            !in 10..20 -> Log.i("mxp", "x is outside the range")
            else -> {
                Log.i("mxp", "whenValue...other")
            }
        }

        var y: Any = 'b'
        when(y) {
            is String -> Log.i("mxp", "is String")
            else -> false
        }
    }
}